/**
 * 逐帧动画，要先引用jq
 * 这是设置div的background-image来显示帧的，所以div必须要有宽高才能显示
 * Created by haua on 17/5/14.
 */
(function () {

    window.H = window.H || {};

    /**
     * 获取元素的经过计算后的所有样式
     * */
    H.getComputedStyle = function(elem,classes){
        return (window.getComputedStyle?window.getComputedStyle(elem||document.documentElement,classes||null):elem.currentStyle) || null;
    };
    /**
     * 获取浏览器各种前缀
     * */
    H.prefix = function(){
        var styles = this.getComputedStyle(document.documentElement),
            pre = (Array.prototype.slice
                    .call(styles)
                    .join('')
                    .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
            )[1],
            dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
        return {
            dom: dom,
            lowercase: pre,
            css: '-' + pre + '-',
            js: pre[0].toUpperCase() + pre.substr(1)
        };
    };

    // 0 js计时器驱动，这种方式很耗性能，但是目前没发现卡
    // 1 css3 animation 驱动，这种方式流程很多
    var model = 1,
        animEndEventNames = {
            'webkit' : 'webkitAnimationEnd',
            'o' : 'oAnimationEnd',
            'ms' : 'MSAnimationEnd',
            'moz':'mozTransitionEnd',
            'normal' : 'animationend'
        },
        transitionendName = {
            'webkit' : 'webkitTransitionEnd',
            'o' : 'oTransitionEnd',
            'ms' : 'MSTransitionEnd',
            'normal' : 'transitionend'
        },
        //当css3动画结束时会发生的事件名
        animationend = animEndEventNames[H.prefix().lowercase||'normal'],
        //使用Transition动画结束后的事件
        transitionEnd = transitionendName[H.prefix().lowercase||'normal'];

    //动画参数 aniData 参考
    var aniData = {
        sprite:'tel.png',//雪碧图文件路径，只支持雪碧图
        width:366,//雪碧图每个单元的宽度
        height:320,
        col:1,//有多少行
        row:13,//有多少列
        num:13,//有可能最后一行或最后一列少一两个单元
        order:'left-top',//排列顺序,left-top左到右上到下，目前仅支持这种
        frames:'0,1,2,3,1,2,6,0,', //按照这个排序来播放
        interval:100 //每隔多少毫秒播放下一帧
    };

    /**
     * @param $dom jquery
     * @param aniData obj 动画数据，上面有参考
     * @param loop int 循环次数,0为无限循环，默认为1
     * @param direction bool 是否轮流反向播放，默认false，目前未支持
     * */
    H.animateFrame = function ($dom,aniData,loop,direction) {
        this.sprite = aniData.sprite;
        this.sWidth = aniData.width;
        this.sHeight = aniData.height;
        this.sCol = aniData.col;
        this.sRow = aniData.row;
        this.sOrder = aniData.order;

        this.interval = aniData.interval;

        if(typeof aniData.frames == 'string'){
            this.frames = aniData.frames.split(',');
        }else{
            this.frames = [];
            for(var i=0;i<aniData.frames;i++){
                this.frames.push(i)
            }
        }

        this.frameNum = this.frames.length;
        this.framesPositions = [];

        this.$dom = $dom;
        this.loop = loop===undefined?1:loop;
        this.direction = !!direction;

        this.callFn = [];

        this.nowI = 0;//目前播放的帧
        this.pause = true;

        this.aniName = 'H_animateFrame_'+Math.floor(Math.random()*100000);//生成一个动画名字

        this.reset();
    };

    H.animateFrame.prototype = {
        //初始化，就是设置css，让第一帧显示出来
        reset:function () {
            //播放窗口的大小，不知为何，除了iPhone之外，容器的宽度如果不刚好等于雪碧图一个单元的宽度，
            // background-size和background-position的合作有问题，播放时画面会左右跳动
            // 不论是css3 animate 驱动还是 js setTimeout 驱动都是一样
            var t = this,
                oriWidth = t.$dom.width(),
                scale = oriWidth/t.sWidth,
                scaleText = 'scale('+scale+','+scale+')';
            t.$dom.css({
                'width':t.sWidth,
                'height':t.sHeight,
                '-webkit-transform': scaleText,
                '-moz-transform': scaleText,
                '-ms-transform': scaleText,
                '-o-transform': scaleText,
                'transform': scaleText,
                //不同浏览器的中心点不统一，不设置这个不行
                'transform-origin':'left top',
                '-ms-transform-origin':'left top',
                '-webkit-transform-origin':'left top',
                '-moz-transform-origin':'left top',
                '-o-transform-origin':'left top'
            });

            t.width = t.sWidth;//t.$dom.width()
            t.height = t.sHeight;//t.$dom.height()

            //加个播放结束事件
            if(!t.framesPositions.length){
                t.$dom.on(animationend,function () {
                    t.gotoAndStop(t.frameNum-1);
                    for (var i=0;i<t.callFn.length;i++){
                        t.callFn[i](t);
                    }
                });
            }

            //初始化
            $('style.'+t.aniName+'_style').remove();
            t.framesPositions = [];

            var scaleX = t.width/t.sWidth,
                sw = t.width,
                sh = t.sHeight*scaleX,
                css = '',
                css_key = ['keyframes','-moz-keyframes','-webkit-keyframes','-o-keyframes'],
                cssAniText = '',
                posiTemp = 'JS_X_px JS_Y_px',
                presentTemp = 'JS_present_% {background-position:JS_posi_}';
            for(var i=0;i<t.frameNum;i++){
                var si = t.frames[i],//拿到当前帧在雪碧图中的顺序
                    hi = Math.floor(si/t.sRow),
                    wi = si%t.sRow,
                    posi = posiTemp
                        .replace('JS_X_',-wi*sw)
                        .replace('JS_Y_',-hi*sh);
                cssAniText += presentTemp
                    .replace('JS_present_',i/(t.frameNum-1)*100)
                    .replace('JS_posi_',posi);

                t.framesPositions.push(posi);
            }
            css += '<style type="text/css" rel="stylesheet" class="'+t.aniName+'_style">';
            for (i=0;i<css_key.length;i++){
                css += '@JS_key_ JS_aniName_ {JS_content_}'
                    .replace('JS_key_',css_key[i])
                    .replace('JS_aniName_',t.aniName)
                    .replace('JS_content_',cssAniText);
            }
            css += '</style>';
            $('body').append(css);

            t.$dom.css({
                'background-image':'url('+t.sprite+')',
                'background-size':t.sRow*100 + '%'
            });

            return t;
        },
        gotoAndStop:function (i) {
            this.pause = true;
            this.showFrame(i)
        },
        showFrame:function (i) {
            this.$dom.css({
                'animation':'',
                '-webkit-animation':'',
                'background-position':this.framesPositions[i]
            });
            // alert(this.$dom.css('background-position'));
            // alert(JSON.stringify());

        },
        //播放
        play:function () {
            if(!this.pause)
                return;
            var t = this;
            t.pause = false;
            if(model===0){
                play();
                function play() {
                    setTimeout(function () {
                        if(!t.pause){
                            t.nowI++;
                            t.showFrame(t.nowI%t.frameNum);
                            play();
                        }
                    },t.interval);
                }
            }else{
                var cssText = 'JS_aniName_ JS_time_s steps(JS_step_,start) JS_loop_'
                    .replace('JS_aniName_',t.aniName)
                    .replace('JS_time_',t.interval/1000*t.frameNum)
                    .replace('JS_step_',1)//this.frameNum
                    .replace('JS_loop_',t.loop?t.loop:'infinite');
                this.$dom.css({
                    'animation':cssText,
                    '-webkit-animation':cssText // Safari 和 Chrome
                })
            }
            return t;
        },
        stop:function () {
            this.pause = true;
            this.$dom.css({
                'animation':'',
                '-webkit-animation':'' // Safari 和 Chrome
            });
            return this;
        },
        call:function (fn) {
            var t = this;
            t.callFn.push(fn);
        }
    };

}());
